# encoding: utf-8
"""
把token转化为语法树返回给compiler
"""
from .compile_share import *
from .optimize_data.number_optimize import op_func_dict
from .optimize_data.condit_optimize import cond_func_dict
from . import CRE as TRE

from Error.Error import compile_error as send_error
from loader.func_loader import builtin_func_name
from share import nums


opers_condit = opers + condits
DATA = "data"
BUILTIN_FUNC = "builtin_func"


def ifis(value):
    """简化列表并递归求解表达式
    @param value: 语句，数据，总之一切可以解析的东西，类型没有明确要求
    @return: 解析后的列表
    """
    if (isinstance(value, list)) and (len(value) == 1):
        value = value[0]
        value = (value, DATA)
        return value
    elif len(value) == 0:
        return []
    elif isinstance(value, str):
        return value, DATA
    # 函数 语句 运算符
    return real_grammar([value])


def count_lines(index, codes) -> int:
    """
    对于语句块，通过数{和}的数量来划分行数
    @param index: 目前代码的索引
    @param codes: 目前代码所在的一大串token
    @return: 目前代码的结束行的索引
    """
    # 何时跳出循环
    break_num = 0
    # 跳出循环后的索引
    ingrammar_index = index
    for add in codes[index:]:
        ingrammar_index += 1
        if "{" in add:
            break_num += 1
        elif "}" in add:
            break_num -= 1
            if break_num == 0:
                break
    return ingrammar_index


def in_func(oper_index, code) -> bool:
    """
    判断符号是否处于函数括号内
    @param oper_index: 符号索引
    @param code: 当前语句
    @return: 判断符号是否处于函数括号内的布尔值
    """
    break_num = 0
    symbol_start = 0
    for char in range(len(code)):
        if code[char] == "(":
            break_num += 1
        elif code[char] == ")":
            break_num -= 1
            if break_num == 0:
                symbol_end = char
                break
    return symbol_start < oper_index < symbol_end


def build_condit_tree(code, value) -> list:
    """制作条件
    @param code: 需要解析的条件表达式所在的语句
    @param value: 需要解析的条件表达式
    @return: 条件表达式
    """
    condit = None
    if len(value) != 1:
        # 多个元素
        for jo in condits:
            if jo in code:
                first_value = ifis(value[: value.index(jo)])
                second_value = ifis(value[value.index(jo) + 1 :])
                condit = jo
                break

        if condit is None:
            # 没有找到运算符
            condit_tree = [ifis(value)]
        else:
            # 条件树
            # 尝试常量折叠
            if (
                len(first_value) == len(second_value) == 2
                and isinstance(first_value, tuple)
                and isinstance(second_value, tuple)
                and first_value[1] == DATA
                and second_value[1] == DATA
                and (first_value[0][0] in nums or first_value[0][0] in string)
                and (second_value[0][0] in nums or second_value[0][0] in string)
                and condit in cond_func_dict
                and "." not in first_value[0]
                and "." not in second_value[0]
            ):
                if (first_value[0][0] in nums or first_value[0][0] in string) and (
                    second_value[0][0] in nums or second_value[0][0] in string
                ):
                    # 字符串
                    condit_tree = (
                        str(
                            int(cond_func_dict[condit](first_value[0], second_value[0]))
                        ),
                        DATA,
                    )
                else:
                    # 整数
                    condit_tree = (
                        str(
                            cond_func_dict[condit](
                                int(first_value[0]), int(second_value[0])
                            )
                        ),
                        DATA,
                    )
            else:
                condit_tree = [first_value, second_value, condit]
    else:
        # 一个元素
        condit_tree = [ifis(value)]
    return condit_tree


def assignment(oper: str, code: list) -> list:
    """赋值语句的语法树
    @param oper: 当前所在的语句列表的赋值符号
    @param code: 解析需要解析的赋值语句
    @return: 解析后的列表
    """
    name = (code[0], DATA)
    value = code[code.index(oper) + 1 :]
    value = ifis(value)
    tree = [value, (oper, name)]
    return tree


def symbol(oper, code) -> list:
    """条件表达式的语法树
    @param oper: 当前所在的语句列表的运算符号
    @param code: 解析需要解析的表达式
    @return: 解析后的列表
    运算优先级原理：首先解析优先级低下的表达式以达到优先级效果
    """
    first = code[: code.index(oper)]
    first = ifis(first)
    second = code[code.index(oper) + 1 :]
    second = ifis(second)
    # 尝试常量折叠,注：小数不允许常量折叠
    if (
        len(first) == len(second) == 2
        and isinstance(first, tuple)
        and isinstance(second, tuple)
        and first[1] == DATA
        and second[1] == DATA
        and first[0][0] in nums
        and second[0][0] in nums
        and "." not in first[0]
        and "." not in second[0]
        and oper in op_func_dict
    ):
        # 开始常量折叠
        try:
            tree = (str(op_func_dict[oper](int(first[0]), int(second[0]))), DATA)
        except TypeError:
            send_error("SyntaxError", "invalid syntax")
    else:
        tree = [[first, second], oper]
    return tree


def func_tree(code) -> list:
    """函数
    @param code: 需要解析的函数调用
    @return: 解析后的列表
    """

    def func_parser(value):
        # 参数列表
        add = []
        valuelist = []
        index = 0
        for v in range(len(value)):
            if value[index] != "," and value[index] != ")":
                add.append(value[index])
            elif value[index] == "(":
                # 内函数范围
                in_func_func = value[index - 1 : value.index(")", index - 1)]
                valuelist.append(ifis(in_func_func))
                index += len(in_func_func)
                add = []
            else:
                valuelist.append(ifis(add))
                add = []
            index += 1
        valuelist = valuelist[::-1]
        return valuelist

    name = code[0]
    # 参数（去括号）
    value = code[2:]
    if "," in value:
        # 多个参数
        valuelist = func_parser(value)
        long = str(len(valuelist))
    elif len(value) != 1:
        # 一个参数
        value = value[:-1]
        valuelist = ifis(value)
        # 参数长度
        long = "1"
    else:
        valuelist = []
        long = "0"

    if name in builtin_func_name:
        name = (name, BUILTIN_FUNC)
    tree = [valuelist, (long, DATA), name]
    return tree


def sentence_tree(code) -> list:
    """语句
    @param code: 需要解析的列表：
    语句示例：import app
    @return: 解析后的列表
    """
    name = code[0]
    value = code[1:]
    if len(value) == 0:
        tree = [code[0]]
    else:
        tree = [ifis(value), name]
    return tree


def while_tree(code, value, grammar_index, codes) -> list:
    """条件循环语法树
    @param code: 当前所在语句
    @param value: 语句的参数
    @param grammar_index: 当前语句在列表中的索引
    @param codes: 当前正在解析的列表
    @return: 组成的条件语法树
    """
    condit_tree = build_condit_tree(code, value)
    ingrammar_index = count_lines(grammar_index, codes)
    codes[ingrammar_index - 1] = ["goto", str(grammar_index)]
    all_tree = [
        (str(ingrammar_index), DATA),
        condit_tree,
        "while",
    ]
    return all_tree


def if_tree(code, value, grammar_index, codes) -> list:
    """条件分支语法树
    @param code: 当前所在语句
    @param value: 语句的参数
    @param grammar_index: 当前语句在列表中的索引
    @param codes: 当前正在解析的列表
    @return: 组成的条件语法树
    """
    condit_tree = build_condit_tree(code, value)
    ingrammar_index = count_lines(grammar_index, codes)
    all_tree = [
        (str(ingrammar_index), DATA),
        condit_tree,
        "if",
    ]
    return all_tree


def def_func_tree(code, value, grammar_index, codes) -> list:
    """函数定义"""
    func_name = value[0]
    argument = value[value.index("(") + 1 : value.index(")")]
    argument = ifis(argument)
    argument_long = str(len(argument))
    ingrammar_index = count_lines(grammar_index, codes)
    all_tree = [
        (str(ingrammar_index), DATA),
        (func_name, DATA),
        argument,
        (argument_long, DATA),
        "func",
    ]
    return all_tree


def build_array_tree(code):
    """
    数组变量的建立
    code:指令
    """
    if "[" in code and "]" in code:
        pass
    else:
        pass
    tree = []
    return tree


def real_grammar(codes: list) -> list:
    """生成语法树
    @param codes: 接受由token解析的列表
    @return: 通过本函数解析过的列表
    """
    return_trees = []
    grammar_index = -1
    while 1:
        grammar_index += 1
        TRE.run_index["__main__"] = grammar_index + 1
        if not grammar_index <= (len(codes) - 1):
            break
        code = codes[grammar_index]
        for i in aslist:
            if i in code:
                # 赋值语句
                return_trees.append(assignment(oper=i, code=code))
                break
        else:
            for i in opers_condit:
                if i in code:
                    # 条件表达式
                    if ("(" not in code) and (")" not in code):
                        # 判断是否处于语句中
                        for j in sentences:
                            if j in code:
                                break
                        else:
                            # 判断是否处于循环中
                            for j in keywords:
                                if j in code:
                                    break
                            else:
                                return_trees.append(symbol(oper=i, code=code))
                                break
                    elif ("(" in code) and (")" in code):
                        # 语句包括于函数
                        if in_func(code.index(i), code):
                            # 如果在函数中，运行函数
                            tree = func_tree(code)
                            return_trees.append(tree)
                            break
                        else:
                            # 如果不在函数中，按正常执行
                            return_trees.append(symbol(oper=i, code=code))
                            break
            else:
                if ("(" in code) and (")" in code) and ("func" not in code):
                    tree = func_tree(code)
                    return_trees.append(tree)
                else:
                    # 语句
                    for j in sentences:
                        if j in code:
                            tree = sentence_tree(code)
                            return_trees.append(tree)
                            break
                    else:
                        if "{" in code:
                            # 除关键字以外的"值"
                            value = code[1 : code.index("{")]
                            if "if" in code:
                                all_tree = if_tree(code, value, grammar_index, codes)
                                return_trees.append(all_tree)

                            elif "while" in code:
                                all_tree = while_tree(code, value, grammar_index, codes)
                                return_trees.append(all_tree)

                            elif "for" in code:
                                pass

                            elif "func" in code:
                                all_tree = def_func_tree(
                                    code, value, grammar_index, codes
                                )
                                return_trees.append(all_tree)
                        else:
                            # 如果不满足任何条件，直接返回原句
                            return_trees.append(code)

    return return_trees


def grammar(codes: list) -> list:
    """
    本函数为一张空壳，目的是封装real_grammar函数，实现还原TRE的效果
    """
    # TRE开始的地方
    START = TRE.run_index["__main__"]
    TRE.run_index["__main__"] = 0
    result_codes = real_grammar(codes)
    TRE.run_index["__main__"] = START
    return result_codes
